/**
 * panel - jQuery xui
 *
 * Licensed under the GPL:
 *   http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2013 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    function setSize(target, param) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var header = panel.find('>div.panel-header');
        var body = panel.find('>div.panel-body');

        if (param) {
            if (param.width) {
                opts.width = param.width;
            }
            if (param.height) {
                opts.height = param.height;
            }
            if (param.left != null) {
                opts.left = param.left;
            }
            if (param.top != null) {
                opts.top = param.top;
            }
        }
        if (opts.fit) {
            $.extend(opts, panel._fit());
        } else {
            panel._fit(false);
        }

        panel.css({
            left: opts.left,
            top: opts.top
        });
        panel.css(opts.style);
        panel.addClass(opts.cls);
        header.addClass(opts.headerCls);
        body.addClass(opts.bodyCls);

        if (!isNaN(opts.width)) {
            panel._outerWidth(opts.width);
            header._outerWidth(panel.width());
            body._outerWidth(panel.width());
        } else {
            panel.width('auto');
            body.width('auto');
        }
        if (!isNaN(opts.height)) {
            panel._outerHeight(opts.height);
            body._outerHeight(panel.height() - header.outerHeight());
        } else {
            body.height('auto');
        }

        opts.onResize.apply(target, [opts.width, opts.height]);
    }

    function movePanel(target, param) {
        var opts = $.data(target, 'panel').options;
        var panel = $.data(target, 'panel').panel;
        if (param) {
            if (param.left != null) opts.left = param.left;
            if (param.top != null) opts.top = param.top;
        }
        panel.css({
            left: opts.left,
            top: opts.top
        });
        opts.onMove.apply(target, [opts.left, opts.top]);
    }

    function wrapPanel(target) {
        var panel = $(target).addClass('panel-body').wrap('<div class="panel"></div>').parent();

        return panel;
    }

    function buildPanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        panel.find('>div.panel-header').remove();
        //header
        if (!opts.noheader) {
            var header = $('<div class="panel-header"><div class="panel-title">' + (opts.title ? opts.title : '&nbsp;') + '</div></div>').prependTo(panel);
            if (opts.iconCls) {
                header.find('.panel-title').addClass('panel-with-icon');
                $('<div class="panel-icon"></div>').addClass(opts.iconCls).appendTo(header);
            }
            var tool = $('<div class="panel-tool"></div>').appendTo(header);
            if (opts.collapsible) {
                $('<a href="javascript:void(0)" class="panel-tool-collapse"></a>').appendTo(tool).bind('click', onToggle);
            }
            if (opts.minimizable) {
                $('<a href="javascript:void(0)" class="panel-tool-min"></a>').appendTo(tool).bind('click', onMin);
            }
            if (opts.maximizable) {
                $('<a href="javascript:void(0)" class="panel-tool-max"></a>').appendTo(tool).bind('click', onMax);
            }
            if (opts.closable) {
                $('<a href="javascript:void(0)" class="panel-tool-close"></a>').appendTo(tool).bind('click', onClose);
            }
            if (opts.tools) {
                for (var i = 0; i < opts.tools.length; i++) {
                    var t = $('<a href="javascript:void(0)"></a>').addClass(opts.tools[i].iconCls).appendTo(tool);
                    if (opts.tools[i].style) {
                        t.css(opts.tools[i].style)
                    }
                    if (opts.tools[i].handler) {
                        t.bind('click', opts.tools[i].handler);
                    }
                }
            }
            tool.find('a').hover(
                function() {
                    $(this).addClass('panel-tool-over');
                },
                function() {
                    $(this).removeClass('panel-tool-over');
                }
            );
            panel.find('>div.panel-body').removeClass('panel-body-noheader');
        } else {
            panel.find('>div.panel-body').addClass('panel-body-noheader');
        }

        //body
        if (opts.content) { //本地数据
            $(target).html(opts.content);
            if ($.parser) {
                //$.parser.parse(target);
            }
        }
        loadData(target); //远程数据

        //边框
        if (opts.border == true) {
            panel.find('>div.panel-header').removeClass('panel-header-noborder');
            panel.find('>div.panel-body').removeClass('panel-body-noborder');
        } else {
            panel.find('>div.panel-header').addClass('panel-header-noborder');
            panel.find('>div.panel-body').addClass('panel-body-noborder');
        }

        function onToggle() {
            if ($(this).hasClass('panel-tool-expand')) {
                expandPanel(target, true);
            } else {
                collapsePanel(target, true);
            }
            return false;
        }

        function onMin() {
            minimizePanel(target);
            return false;
        }

        function onMax() {
            if ($(this).hasClass('panel-tool-restore')) {
                restorePanel(target);
            } else {
                maximizePanel(target);
            }
            return false;
        }

        function onClose() {
            closePanel(target);
            return false;
        }
    }

    /**
     * 如果定义了href,则加载远程数据
     */
    function loadData(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        if (opts.href && !state.isLoaded) {
            if (opts.onBeforeLoad.call(target) == false)
                return;
            state.isLoaded = false;
            opts.onBeforeLoad.apply(target, arguments);
            var pbody = state.panel.find('>div.panel-body');
            pbody.html($('<div class="panel-loading"></div>').html(opts.loadingMessage));
            pbody.load(opts.href, null, function() {
                if ($.parser) {
                    $.parser.parse(pbody);
                }
                opts.onLoad.apply(target, arguments);
                state.isLoaded = true;
            });
        }
    }

    function openPanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        if (opts.onBeforeOpen.call(target) == false)
            return;

        panel.show();
        opts.closed = false;
        opts.onOpen.call(target);
    }

    function closePanel(target) {
        var state = $.data(target, 'panel');
        var original = $.data(target, 'panel').original;
        var opts = state.options;
        var panel = state.panel;

        if (opts.onBeforeClose.call(target) == false)
            return;
		
		var original = state.original;
        if(original) {
			panel._fit(original.fit);	
		}
        panel.hide();
        opts.closed = true;
        opts.onClose.call(target);
    }

    function destroyPanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;

        if (opts.onBeforeDestroy.call(target) == false)
            return;

        panel.remove();
        opts.onDestroy.call(target);
    }

    function collapsePanel(target, animate) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var body = panel.find('>div.panel-body');
        var tool = panel.find('>div.panel-header .panel-tool-collapse');

        if (tool.hasClass('panel-tool-expand')) return;

        body.stop(true, true); // stop animation
        if (opts.onBeforeCollapse.call(target) == false) return;

        tool.addClass('panel-tool-expand');
        if (animate == true) {
            body.slideUp('normal', function() {
                opts.collapsed = true;
                opts.onCollapse.call(target);
            });
        } else {
            body.hide();
            opts.collapsed = true;
            opts.onCollapse.call(target);
        }
    }

    function expandPanel(target, animate) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var body = panel.find('>div.panel-body');
        var tool = panel.find('>div.panel-header .panel-tool-collapse');

        if (!tool.hasClass('panel-tool-expand')) return;

        body.stop(true, true); // stop animation
        if (opts.onBeforeExpand.call(target) == false) return;

        tool.removeClass('panel-tool-expand');
        if (animate == true) {
            body.slideDown('normal', function() {
                opts.collapsed = false;
                opts.onExpand.call(target);
                loadData(target);
            });
        } else {
            body.show();
            opts.collapsed = false;
            opts.onExpand.call(target);
            loadData(target);
        }
    }

    function maximizePanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var tool = panel.find('>div.panel-header .panel-tool-max');

        if (tool.hasClass('panel-tool-restore')) {
            return;
        }

        tool.addClass('panel-tool-restore');

        $.data(target, 'panel').original = {
            width: opts.width,
            height: opts.height,
            left: opts.left,
            top: opts.top,
            fit: opts.fit
        };
        opts.left = 0;
        opts.top = 0;
        opts.fit = true;
        setSize(target);
        opts.minimized = false;
        opts.maximized = true;
        opts.onMaximize.call(target);
    }

    function minimizePanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var original = state.original;
        if(original) {
			panel._fit(original.fit);	
		}
        panel.hide();
        opts.minimized = true;
        opts.maximized = false;
        opts.onMinimize.call(target);
    }

    function restorePanel(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        var tool = panel.find('>div.panel-header .panel-tool-max');

        if (!tool.hasClass('panel-tool-restore')) return;

        panel.show();
        tool.removeClass('panel-tool-restore');
        var original = $.data(target, 'panel').original;
        opts.width = original.width;
        opts.height = original.height;
        opts.left = original.left;
        opts.top = original.top;
        opts.fit = original.fit;
        setSize(target);
        opts.minimized = false;
        opts.maximized = false;
        opts.onRestore.call(target);
    }

    function setTitle(target, title) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        var panel = state.panel;
        opts.title = title;
        panel.find('>div.panel-header div.panel-title').html(title);
    }

    $.fn.panel = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.panel.methods[options](this, param);
        }
        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'panel');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
                state.isLoaded = false;
            } else {
                opts = $.extend({}, $.fn.panel.defaults, $.fn.panel.parseOptions(this), options);
                state = $.data(this, 'panel', {
                    options: opts,
                    panel: wrapPanel(this),
                    isLoaded: false
                });
            }
            buildPanel(this);
            if (opts.doSize == true) {
                state.panel.css('display', 'block');
                setSize(this);
            }
            if (opts.closed == true || opts.minimized == true) {
                state.panel.hide();
            } else {
                openPanel(this);
            }
        });
    };

    $.fn.panel.methods = {
        options: function(jq) {
            return $.data(jq[0], 'panel').options;
        },
        panel: function(jq) {
            return $.data(jq[0], 'panel').panel;
        },
        header: function(jq) {
            return $.data(jq[0], 'panel').panel.find('>div.panel-header');
        },
        body: function(jq) {
            return $.data(jq[0], 'panel').panel.find('>div.panel-body');
        },
        setTitle: function(jq, param) {
            return jq.each(function() {
                setTitle(this, param);
            });
        },
        open: function(jq) {
            return jq.each(function() {
                openPanel(this);
            });
        },
        close: function(jq) {
            return jq.each(function() {
                closePanel(this);
            });
        },
        destroy: function(jq) {
            return jq.each(function() {
                destroyPanel(this);
            });
        },
        refresh: function(jq, param) {
            return jq.each(function() {
                $.data(this, 'panel').isLoaded = false;
                if (param) {
                    $.data(this, 'panel').options.href = param;
                }
                loadData(this);
            });
        },
        resize: function(jq, param) {
            return jq.each(function() {
                setSize(this, param);
            });
        },
        move: function(jq, param) {
            return jq.each(function() {
                movePanel(this, param);
            });
        }
    };

    $.fn.panel.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target, ['id', 'width', 'height', 'left', 'top', 'title', 'iconCls', 'cls', 'headerCls', 'bodyCls', 'tools', 'href', , 'loadingMessage', {
            fit: 'boolean',
            border: 'boolean',
            noheader: 'boolean',
            closed: 'boolean'
        }]));
    };

    $.fn.panel.defaults = {
        title: null,
        iconCls: null,
        width: 'auto',
        height: 'auto',
        left: null,
        top: null,
        cls: null,
        headerCls: null,
        bodyCls: null,
        style: {},
        href: null,
        fit: false,
        border: true,
        doSize: true,
        noheader: false,
        content: null,
        //工具
        collapsible: false,
        minimizable: false,
        maximizable: false,
        closable: false,
        collapsed: false,
        minimized: false,
        maximized: false,
        closed: false,
        tools: null,
        href: null,
        loadingMessage: '加载中。。。',
        onBeforeLoad: function() {},
        onLoad: function() {},
        onBeforeOpen: function() {},
        onOpen: function() {},
        onBeforeClose: function() {},
        onClose: function() {},
        onBeforeDestroy: function() {},
        onDestroy: function() {},
        onResize: function(width, height) {},
        onMove: function(left, top) {},
        onMaximize: function() {},
        onRestore: function() {},
        onMinimize: function() {},
        onBeforeCollapse: function() {},
        onBeforeExpand: function() {},
        onCollapse: function() {},
        onExpand: function() {}
    };
})(jQuery);
